#include "IDigraph.h"
#include "Algorithms.h"
#include "Testing.h"
#include <vector>
#include <string>
#include <iostream>
#include <stdlib.h>
#include <crtdbg.h>

void exitWithUsageError()
{
	std::cerr << "USAGE: -t // to launch testing sequence.\n";
	std::cerr << "USAGE: <test_file> // to solve 2-SAT problem in following format:" << std::endl;
	std::cerr << "N M - number of disjunctions and variables\n";
	std::cerr << "[-]x [-]y - disjunction; all variables are numbers from 1 to M; if variable in format \"-x\" then it is negated" << std::endl;
	exit(1);
}

std::unique_ptr<IDigraph> prepareInput(char* filename)
{
	FILE* fin = fopen(filename, "r");
	int disjunctions, variables;
	fscanf(fin, "%d %d", &disjunctions, &variables);
	std::vector<Edge> edges(0);
	for (int i = 0; i < disjunctions; i++)
	{
		int first, second;
		fscanf(fin, "%d %d", &first, &second);
		if (first < 0) first = -first - 1 + variables;
		else first = first - 1;
		if (second < 0) second = -second - 1 + variables;
		else second = second - 1;
		edges.push_back(Edge((first >= variables ? first - variables : first + variables), second));
		edges.push_back(Edge((second >= variables ? second - variables : second + variables), first));
	}
	return makeCompactGraph(edges, variables * 2);
}

int main(int argc, char** argv)
{
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
	setRandSeed(12345679);
	if (argc != 2)
		exitWithUsageError();
	if (strcmp(argv[1], "-t") == 0)
	{
		std::cerr << "Testing basic graph activity.\n";
		testBasic();
		std::cerr << "Testing Tarjan`s algorithm.\n";
		testTarjan();
		std::cerr << "Testing 2-SAT solution.\n";
		test2SAT();
		return 0;
	}

	std::unique_ptr<IDigraph> graph = prepareInput(argv[1]);
	int variables = graph->getNumberOfVertices() / 2;
	std::vector<int> result = solve2SAT(graph, variables);
	if (result[0] == -1) std::cout << "No solution." << std::endl;
	else
	{
		std::cout << "Solution is:" << std::endl;
		for (int i = 0; i < variables; i++)
			std::cout << i + 1 << " -- " << (result[i] == 0 ? "false" : "true") << std::endl;
	}
	return 0;
}